{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"images/logo-64x64.png\"/>\n",
    "<h1>Reference Guide for Calysto Scheme</h1>\n",
    "\n",
    "[Calysto Scheme](https://github.com/Calysto/calysto_scheme) is a real Scheme programming language, with full support for continuations, including call/cc. It can also use all Python libraries. Also has some extensions that make it more useful (stepper-debugger, choose/fail, stack traces), or make it better integrated with Python.\n",
    "\n",
    "In Jupyter notebooks, because Calysto Scheme uses [MetaKernel](https://github.com/Calysto/metakernel/blob/master/README.rst), it has a fully-supported set of \"magics\"---meta-commands for additional functionality. This includes running Scheme in parallel. See all of the [MetaKernel Magics](https://github.com/Calysto/metakernel/blob/master/metakernel/magics/README.md).\n",
    "\n",
    "Calysto Scheme is written in Scheme, and then translated into Python (and other backends). The entire functionality lies in a single Python file: https://github.com/Calysto/calysto_scheme/blob/master/calysto_scheme/scheme.py However, you can easily install it (see below).\n",
    "\n",
    "Please see [Calysto Scheme Language](Calysto%20Scheme%20Language.ipynb) for more details on the Calysto Scheme language.\n",
    "\n",
    "## Installation\n",
    "\n",
    "You can install Calysto Scheme with Python3:\n",
    "\n",
    "```\n",
    "pip3 install --upgrade calysto-scheme --user -U\n",
    "python3 -m calysto_kernel install --user\n",
    "```\n",
    "\n",
    "or in the system kernel folder with:\n",
    "\n",
    "```\n",
    "sudo pip3 install --upgrade calysto-scheme -U\n",
    "sudo python3 -m calysto_kernel install\n",
    "```\n",
    "\n",
    "Change pip3/python3 to use a different pip or Python. The version of Python used will determine how Calysto Scheme is run.\n",
    "\n",
    "Use it in the console, qtconsole, or notebook with IPython 3:\n",
    "\n",
    "```\n",
    "ipython console --kernel calysto_scheme\n",
    "ipython qtconsole --kernel calysto_scheme\n",
    "ipython notebook --kernel calysto_scheme\n",
    "```\n",
    "\n",
    "In addition to all of the following items, Calysto Scheme also has access to all of Python's builtin functions, and all of Python's libraries. For example, you can use `(complex 3 2)` to create a complex number by calling Python's complex function.\n",
    "\n",
    "## Jupyter Enhancements\n",
    "\n",
    "When you run Calysto Scheme in Jupyter (console, notebook, qtconsole, etc.) you get:\n",
    "\n",
    "* TAB completions of Scheme functions and variable names\n",
    "* display of rich media\n",
    "* stepper/debugger\n",
    "* magics (% macros)\n",
    "* shell commands (! command)\n",
    "* LaTeX equations\n",
    "* LaTeX-style variables\n",
    "* Python integration"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LaTeX-style variables\n",
    "\n",
    "Calysto Scheme allows you to use LaTeX-style variables in code. For example, if you type:\n",
    "\n",
    "```\n",
    "\\beta\n",
    "```\n",
    "\n",
    "with the cursor right after the 'a' in beta, and then press TAB, it will turn into the unicode character:\n",
    "\n",
    "```\n",
    "β\n",
    "```\n",
    "\n",
    "There are nearly 1300 different symbols defined (thanks to the Julia language) and documented here:\n",
    "\n",
    "http://docs.julialang.org/en/release-0.4/manual/unicode-input/#man-unicode-input\n",
    "\n",
    "Calysto Scheme may not implement all of those. Some useful and suggestive ones:\n",
    "\n",
    "* \\pi - π\n",
    "* \\Pi - Π\n",
    "* \\Sigma - Σ\n",
    "* \\_i - subscript i, such as vectorᵢ"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define α 67)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "α"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define i 2)\n",
    "(define vectorᵢ (vector-ref (vector 0 6 3 2) i))\n",
    "vectorᵢ"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Rich media"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(import \"calysto.display\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(calysto.display.HTML \"This is <b>bold</b>, <i>italics</i>, <u>underlined</u>.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(import \"calysto.graphics\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define canvas (calysto.graphics.Canvas))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define ball (calysto.graphics.Circle '(150 150) 100))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(ball.draw canvas)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Shell commands"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! ls /tmp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Stepper/Debugger\n",
    "\n",
    "Here is what the debugger looks like:\n",
    "\n",
    "<img src=\"images/stepper_debugger.png\">\n",
    "\n",
    "It has breakpoints (click in left margin). You must press Stop to exit the debugger."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```scheme\n",
    "%%debug\n",
    "\n",
    "(begin\n",
    " (define x 1)\n",
    " (set! x 2)\n",
    ")\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Python Integration\n",
    "\n",
    "You can import and use any Python library in Calysto Scheme.\n",
    "\n",
    "In addition, if you wish, you can execute expressions and statements in a Python environment:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(python-eval \"1 + 2\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(python-exec \n",
    "\"\n",
    "def mypyfunc(a, b):\n",
    "    return a * b\n",
    "\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is a shared environment with Scheme:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(mypyfunc 4 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can use `func` to turn a Scheme procedure into a Python function, and `define!` to put it into the shared enviornment with Python:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define! mypyfunc2 (func (lambda (n) n)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(python-eval \"mypyfunc2(34)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Differences Between Languages\n",
    "\n",
    "## Major differences between Scheme and Python\n",
    "\n",
    "1. In Scheme, double quotes are used for strings and may contain newlines\n",
    "1. In Scheme, a single quote is short for (quote ...) and means \"literal\"\n",
    "1. In Scheme, everything is an expression and has a return value\n",
    "1. Python does not support macros (e.g., extending syntax)\n",
    "1. In Python, \"if X\" is false if X is None, False, [], (,) or 0. In Scheme, \"if X\" is only false if X is #f or 0\n",
    "1. Calysto Scheme uses continuations, not the call stack. However, for debugging there is a pseudo-stack when an error is raised. You can trun that off with (use-stack-trace #f)\n",
    "1. Scheme procedures are not Python functions, but there are means to use one as the other.\n",
    "\n",
    "## Major Differences Between Calysto Scheme and other Schemes\n",
    "\n",
    "1. define-syntax works slightly differently\n",
    "1. In Calysto Scheme, #(...) is short for '#(...)\n",
    "1. Calysto Scheme is missing many standard functions (see list at bottom)\n",
    "1. Calysto Scheme has a built-in amb operator called `choose`\n",
    "1. For debugging there is a pseudo-stack when errors are raised in Calysto Scheme. You can trun that off with (use-stack-trace #f)\n",
    "\n",
    "### Stack Trace\n",
    "\n",
    "Calysto Scheme acts as if it has a call stack, for easier debugging. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define fact\n",
    "    (lambda (n)\n",
    "      (if (= n 1)\n",
    "           q\n",
    "           (* n (fact (- n 1))))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(fact 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To turn off the stack trace on error:\n",
    "\n",
    "```scheme\n",
    "(use-stack-trace #f)\n",
    "```\n",
    "That will allow infinite recursive loops without keeping track of the \"stack\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Calysto Scheme Variables\n",
    "\n",
    "## SCHEMEPATH\n",
    "SCHEMEPATH is a list of search directories used with (load NAME). This is a reference, so you should append to it rather than attempting to redefine it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SCHEMEPATH"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(set-cdr! (cdr SCHEMEPATH) (list \"/var/modules\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SCHEMEPATH"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting Started\n",
    "\n",
    "Note that you can use the word `lambda` or \\lambda and then press [TAB]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define factorial\n",
    "  (λ (n)\n",
    "     (cond\n",
    "      ((zero? n) 1)\n",
    "      (else (* n (factorial (- n 1)))))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(factorial 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## define-syntax\n",
    "(define-syntax NAME RULES): a method for creating macros"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define-syntax time \n",
    "  [(time ?exp) (let ((start (current-time)))\n",
    "                 ?exp\n",
    "                 (- (current-time) start))])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(time (car '(1 2 3 4)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    ";;---------------------------------------------------------------------\n",
    ";; collect is like list comprehension in Python\n",
    "\n",
    "(define-syntax collect\n",
    "  [(collect ?exp for ?var in ?list)\n",
    "   (filter-map (lambda (?var) ?exp) (lambda (?var) #t) ?list)]\n",
    "  [(collect ?exp for ?var in ?list if ?condition)\n",
    "   (filter-map (lambda (?var) ?exp) (lambda (?var) ?condition) ?list)])\n",
    "\n",
    "(define filter-map\n",
    "  (lambda (f pred? values)\n",
    "    (if (null? values)\n",
    "      '()\n",
    "      (if (pred? (car values))\n",
    "          (cons (f (car values)) (filter-map f pred? (cdr values)))\n",
    "          (filter-map f pred? (cdr values))))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(collect (* n n) for n in (range 10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(collect (* n n) for n in (range 5 20 3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(collect (* n n) for n in (range 10) if (> n 5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    ";;---------------------------------------------------------------------\n",
    ";; for loops\n",
    "\n",
    "(define-syntax for\n",
    "  [(for ?exp times do . ?bodies)\n",
    "   (for-repeat ?exp (lambda () . ?bodies))]\n",
    "  [(for ?var in ?exp do . ?bodies)\n",
    "   (for-iterate1 ?exp (lambda (?var) . ?bodies))]\n",
    "  [(for ?var at (?i) in ?exp do . ?bodies)\n",
    "   (for-iterate2 0 ?exp (lambda (?var ?i) . ?bodies))]\n",
    "  [(for ?var at (?i ?j . ?rest) in ?exp do . ?bodies)\n",
    "   (for ?var at (?i) in ?exp do\n",
    "     (for ?var at (?j . ?rest) in ?var do . ?bodies))])\n",
    "\n",
    "(define for-repeat\n",
    "  (lambda (n f)\n",
    "    (if (< n 1)\n",
    "      'done\n",
    "      (begin\n",
    "        (f)\n",
    "        (for-repeat (- n 1) f)))))\n",
    "\n",
    "(define for-iterate1\n",
    "  (lambda (values f)\n",
    "    (if (null? values)\n",
    "      'done\n",
    "      (begin\n",
    "        (f (car values))\n",
    "        (for-iterate1 (cdr values) f)))))\n",
    "\n",
    "(define for-iterate2\n",
    "  (lambda (i values f)\n",
    "    (if (null? values)\n",
    "      'done\n",
    "      (begin\n",
    "        (f (car values) i)\n",
    "        (for-iterate2 (+ i 1) (cdr values) f)))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define matrix2d\n",
    "  '((10 20)\n",
    "    (30 40)\n",
    "    (50 60)\n",
    "    (70 80)))\n",
    "\n",
    "(define matrix3d\n",
    "  '(((10 20 30) (40 50 60))\n",
    "    ((70 80 90) (100 110 120))\n",
    "    ((130 140 150) (160 170 180))\n",
    "    ((190 200 210) (220 230 240))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(begin \n",
    " (define hello 0)\n",
    " (for 5 times do (set! hello (+ hello 1)))\n",
    " hello\n",
    " )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(for sym in '(a b c d) do (define x 1) (set! x sym) (print x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(for n in (range 10 20 2) do (print n))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(for n at (i j) in matrix2d do (print (list n 'coords: i j)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(for n at (i j k) in matrix3d do (print (list n 'coords: i j k)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(define-syntax scons\n",
    "  [(scons ?x ?y) (cons ?x (lambda () ?y))])\n",
    "\n",
    "(define scar car)\n",
    "\n",
    "(define scdr\n",
    "  (lambda (s)\n",
    "    (let ((result ((cdr s))))\n",
    "      (set-cdr! s (lambda () result))\n",
    "      result)))\n",
    "\n",
    "(define first\n",
    "  (lambda (n s)\n",
    "    (if (= n 0)\n",
    "      '()\n",
    "      (cons (scar s) (first (- n 1) (scdr s))))))\n",
    "\n",
    "(define nth\n",
    "  (lambda (n s)\n",
    "    (if (= n 0)\n",
    "      (scar s)\n",
    "      (nth (- n 1) (scdr s)))))\n",
    "\n",
    "(define smap\n",
    "  (lambda (f s)\n",
    "    (scons (f (scar s)) (smap f (scdr s)))))\n",
    "\n",
    "(define ones (scons 1 ones))\n",
    "\n",
    "(define nats (scons 0 (combine nats + ones)))\n",
    "\n",
    "(define combine\n",
    "  (lambda (s1 op s2)\n",
    "    (scons (op (scar s1) (scar s2)) (combine (scdr s1) op (scdr s2)))))\n",
    "\n",
    "(define fibs (scons 1 (scons 1 (combine fibs + (scdr fibs)))))\n",
    "\n",
    "(define facts (scons 1 (combine facts * (scdr nats))))\n",
    "\n",
    "(define ! (lambda (n) (nth n facts)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(! 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(nth 10 facts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(nth 20 fibs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(first 30 fibs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## for-each\n",
    "(for-each PROCEDURE LIST): apply PROCEDURE to each item in LIST; like `map` but don't return results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(for-each (lambda (n) (print n)) '(3 4 5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## format\n",
    "(format STRING ITEM ...): format the string with ITEMS as arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(format \"This uses formatting ~a ~s ~%\" 'apple 'apple)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## func\n",
    "\n",
    "Turns a lambda into a Python function.\n",
    "\n",
    "(func (lambda ...))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(func (lambda (n) n))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## There's more!\n",
    "\n",
    "Please see [Calysto Scheme Language](Calysto%20Scheme%20Language.ipynb) for more details on the Calysto Scheme language."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Calysto Scheme (Python)",
   "language": "scheme",
   "name": "calysto_scheme"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "scheme"
   },
   "mimetype": "text/x-scheme",
   "name": "scheme",
   "pygments_lexer": "scheme"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
